package com.smartwebx.ha.web.gis.module.screen;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;

import com.alibaba.citrus.service.requestcontext.parser.ParameterParser;
import com.alibaba.citrus.turbine.TurbineRunData;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.common.base.Objects;
import com.google.common.primitives.Ints;
import com.smartwebx.ha.dal.annot.JsonMixIn;
import com.smartwebx.ha.dal.annot.JsonModule;
import com.smartwebx.ha.dal.annot.JsonModules;

public class BasicScreen {
	private final String METHOD_NAME = "method";
	private final String DATE_FORMAT = "yyyy-MM-dd";
	private final String TIME_FORMAT = "yyyy-MM-dd HH:mm";
	private final String JSON_SUFFIX = "json";

	public Object execute(TurbineRunData rundata) throws Exception {
		ObjectMapper mapper = new ObjectMapper();

		Object result = null;
		String target = rundata.getTarget();
		LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
		// 获得浏览器传递的参数
		ParameterParser params = rundata.getParameters();
		// 获得要执行的方法名
		String methodName = params.getString(METHOD_NAME);
		Class<? extends BasicScreen> clazz = this.getClass();

		int findMethodIndex = 0;
		Method[] methods = clazz.getMethods();
		for (Method m : methods) {
			if (Objects.equal(methodName, m.getName())) {
				// 获得方法的参数名
				String[] paramNames = u.getParameterNames(m);
				// 参数类型
				Class<?>[] paramTypes = m.getParameterTypes();
				// 需要传递的参数
				Object[] args = new Object[paramNames.length];

				for (int i = 0; i < paramTypes.length; i++) {
					Class<?> type = paramTypes[i];
					String paramName = paramNames[i];
					String paramVal = params.getString(paramName);
					if (paramVal == null)
						continue;
					Object arg = paramVal;
					if (type == Date.class) {// 如果参数类型微 Date 类型，则进行转换
						try {
							arg = DateUtils.parseDate(paramVal, DATE_FORMAT,
									TIME_FORMAT);
						} catch (ParseException e) {
							e.printStackTrace();
						}
					} else if (type == Integer.class) {
						arg = Ints.tryParse(paramVal);
					}
					args[i] = arg;
				}

				if (checkedParams(args)) {
					try {
						// 执行方法，获得结果
						result = MethodUtils.invokeMethod(this, methodName,
								args, paramTypes);
					} catch (NoSuchMethodException | IllegalAccessException
							| InvocationTargetException e) {
						e.printStackTrace();
					}
				} else {
					result = "请求缺少参数";
				}

				// 如果没有结果，返回空字符串
				if (result == null) {
					result = "";
				} else {
					// 判断是否返回json数据
					if (this.checkSuffixIsJson(target)) {
						result = this.annotationRegister(mapper,
								m.getAnnotations(), result);
					}
				}
				break;
			}
			findMethodIndex++;

			if (findMethodIndex == methods.length - 1) {
				// 如果没有匹配方法，则在控制台中打印出一场
				throw new Exception("未找到匹配（" + methodName + "）的方法");
			}
		}

		return result;
	}

	private Boolean checkedParams(Object[] params) {
		boolean pass = true;
		for (Object param : params) {
			if (param == null)
				pass = false;
		}

		return pass;
	}

	private Object annotationRegister(ObjectMapper mapper,
			Annotation[] annotations, Object result) throws Exception {
		Class<?> moduleClazz = null;
		String value = null;
		boolean isNumber = false;
		SimpleModule module = null;
		if (annotations != null && annotations.length > 0) {
			// 循环接收到的注解
			for (int i = 0; i < annotations.length; i++) {
				Annotation annotation = annotations[i];
				// 判断注解类型
				if (annotation.annotationType() == JsonModules.class) {
					JsonModules jsonModules = (JsonModules) annotation;

					for (JsonModule jsonModule : jsonModules.value()) {
						moduleClazz = jsonModule.clazz();
						value = jsonModule.value();
						// 得到注解中用到的自定义module名
						module = this.buildModule(moduleClazz, value, isNumber);
						// 执行定义的module
						mapper.registerModule(module);
					}
				} else if (annotation.annotationType() == JsonModule.class) {
					JsonModule jsonModule = (JsonModule) annotation;

					moduleClazz = jsonModule.clazz();
					value = jsonModule.value();
					isNumber = jsonModule.isNumber();
					module = this.buildModule(moduleClazz, value, isNumber);
					mapper.registerModule(module);
				} else if (annotation.annotationType() == JsonMixIn.class) {
					JsonMixIn jsonMixIn = (JsonMixIn) annotation;
					Class<?> target = jsonMixIn.target();
					Class<?> mixinSou = jsonMixIn.mixinSou();
					mapper.addMixInAnnotations(target, mixinSou);
				}
			}
		}
		result = mapper.writeValueAsString(result);
		return result;
	}

	private SimpleModule buildModule(Class<?> moduleClazz, String value,
			boolean isNumber) throws Exception {
		SimpleModule module = null;
		if (isNumber && !"".equals(value)) {
			Constructor<?> constructor = moduleClazz
					.getConstructor(Object.class,Object.class);
			// 得到定义的module类型
			module = (SimpleModule) constructor.newInstance(value, isNumber);
		} else if (!"".equals(value)) { // 需要执行一个但参数的构造函数
			Constructor<?> constructor = moduleClazz
					.getConstructor(Object.class);
			// 得到定义的module类型
			module = (SimpleModule) constructor.newInstance(value);
		} else {
			module = (SimpleModule) moduleClazz.newInstance();
		}
		return module;
	}

	private boolean checkSuffixIsJson(String target) {
		if (target == null)
			return false;
		String suffix = target.substring(target.lastIndexOf('.') + 1);
		return JSON_SUFFIX.equalsIgnoreCase(suffix);
	}

}
